import clsx from 'clsx';
import React, { useCallback, useMemo } from 'react';
import { Waterfall, WaterfallProps } from 'src/components/Waterfall';
import {
  IntersectionObserver,
  IntersectionObserverProps,
} from 'src/components/IntersectionObserver';
import { ImageView } from 'src/components/ImageView';
import { FolderFilled } from '@ant-design/icons';
import { Dropdown } from 'src/components/Dropdown';
import { EllipsisVerticalIcon, PencilSquareIcon, TrashIcon } from '@heroicons/react/24/outline';
import type { ExplorerImageItem, ExplorerItem } from 'src/hooks/useExplorerInfiniteScroll';

export interface GridViewProps {
  className?: string;
  root: IntersectionObserverProps['root'];
  dataSource: ExplorerItem[];
  selectedKeys?: string[];
  onSelect?: (selectedKeys: string[]) => void;
  onClick?: (item: ExplorerItem) => void;
}

function GridViewNoMemoized(props: GridViewProps) {
  const { className, root, dataSource, selectedKeys, onSelect, onClick } = props;

  const folderList = useMemo(() => dataSource.filter((i) => i.type === 'folder'), [dataSource]);

  const imageList = useMemo(
    () =>
      dataSource
        .filter((i) => i.type === 'image')
        .map((item) => ({
          ...item,
          width: item.metadata?.width || 200,
          height: item.metadata?.height || 200,
        })),
    [dataSource]
  );

  const handleSP = useCallback((e: React.MouseEvent) => {
    e.stopPropagation();
  }, []);

  const renderItem = useCallback<NonNullable<WaterfallProps<ExplorerImageItem>['renderItem']>>(
    (item) => {
      if (!item.aspectHeight) return null;
      const w = item.aspectWidth.toFixed(0);
      const h = item.aspectHeight.toFixed(0);
      return (
        <IntersectionObserver
          root={root}
          width={item.aspectWidth}
          height={item.aspectHeight}
          rootMargin="-70px"
        >
          {(isIntersecting) => {
            if (!isIntersecting) return <div className="size-full bg-gray-300" />;
            return (
              <div
                role="button"
                className="relative overflow-hidden size-full border shadow-xl rounded-box border-gray-100 dark:border-gray-700 cursor-pointer hover:opacity-75 transition-opacity"
                onClick={() => {
                  onClick?.(item);
                }}
              >
                <div
                  className="inline-flex size-fit rounded-box bg-white/65 dark:bg-black/65 absolute top-2 left-2 z-10"
                  onClick={handleSP}
                  onMouseDown={handleSP}
                >
                  <input
                    type="checkbox"
                    checked={selectedKeys?.includes(item.id)}
                    className="checkbox"
                    onChange={(e) => {
                      const _selectedKeys = selectedKeys?.filter((key) => key !== item.id) ?? [];
                      if (e.target.checked) {
                        _selectedKeys.push(item.id);
                      }
                      onSelect?.(_selectedKeys);
                    }}
                  />
                </div>
                <ImageView
                  src={item.imageUrl + `?w=${w}&h=${h}&format=webp`}
                  alt={item.description ?? item.name}
                  width={item.aspectWidth}
                  height={item.aspectHeight}
                  draggable={false}
                />
              </div>
            );
          }}
        </IntersectionObserver>
      );
    },
    [handleSP, onClick, onSelect, root, selectedKeys]
  );

  return (
    <div className={clsx('flex flex-col items-center gap-5 py-5', className)}>
      {folderList?.length && (
        <div className="grid grid-cols-4 gap-4 w-[848px]">
          {folderList.map((folder) => (
            <div
              key={folder.id}
              role="button"
              className="flex h-10 items-center bg-base-300 px-2 overflow-hidden rounded-box text-left cursor-pointer hover:bg-base-200 active:bg-base-100 transition-colors"
              onClick={() => onClick?.(folder)}
            >
              <div className="flex-none pl-1 pr-2 overflow-hidden text-2xl text-center text-yellow-500">
                <FolderFilled />
              </div>
              <div className="flex-1 text-sm font-semibold inline-block truncate">
                {folder.name}
              </div>
              <div className="flex-none text-right">
                <Dropdown
                  className="btn btn-xs btn-ghost px-1 tooltip tooltip-left [&:where([data-tip]):before]:text-xs [&:where([data-tip]):before]:font-normal"
                  data-tip="更多操作"
                  autoClose
                  singleMode
                  options={[
                    {
                      label: '编辑',
                      value: 'edit',
                      icon: <PencilSquareIcon className="size-4" />,
                      onClick: (option) => {
                        console.log('edit', option);
                      },
                    },
                    {
                      label: '删除',
                      value: 'delete',
                      icon: <TrashIcon className="size-4 !text-red-500" />,
                    },
                  ]}
                >
                  <EllipsisVerticalIcon className="size-4" />
                </Dropdown>
              </div>
            </div>
          ))}
        </div>
      )}
      <Waterfall itemKey="id" cols={4} width={848} list={imageList} renderItem={renderItem} />
    </div>
  );
}

export const GridView = React.memo(GridViewNoMemoized);
